package com.zx.sercurity;

import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;

/**
 * 加速度传感器与陀螺仪监控
 * 5分钟不移动手机将会触发风控
 */
public class MovementDetectorRiskCountDown extends CountDownAsyncRiskControl<Boolean> implements SensorEventListener,Runnable {

    private static final float THRESHOLD_ACCELEROMETER = 0.5f; // 加速度阈值
    private static final float THRESHOLD_GYROSCOPE = 0.1f; // 陀螺仪阈值
    private long lastMovementTime = System.currentTimeMillis();
    private final long TIME_THRESHOLD = 30 * 60 * 1000; // 5分钟
    private SensorManager sensorManager;

    private AsyncResultWrapper<Boolean> resultWrapper = new AsyncResultWrapper<>(ProcessState.IDLE,false,riskType(),false);

    public MovementDetectorRiskCountDown(AsyncRiskListener riskLiveData) {
        super(riskLiveData);
    }


    @Override
    public RiskEnum riskType() {
        return RiskEnum.MovementDetectorRisk;
    }

    @Override
    protected long riskHolderTime() {
        return TIME_THRESHOLD;
    }

    @Override
    protected boolean startUp(Context context) {
        if (sensorManager == null) {
            sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
        }
        Sensor accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        Sensor gyroscope = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
        if (accelerometer != null) {
            sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL);
        }
        if (gyroscope != null) {
            sensorManager.registerListener(this, gyroscope, SensorManager.SENSOR_DELAY_NORMAL);
        }
        if (listener != null){
            resultWrapper = resultWrapper.newState(ProcessState.RUNNING);
            listener.onAsyncRiskStateChange(resultWrapper);
        }
        return true;
    }

    @Override
    protected void startUpCanceled() {
        if (listener != null){
            resultWrapper =  resultWrapper.newState(ProcessState.STOP);
            listener.onAsyncRiskStateChange(resultWrapper);
        }
    }

    @Override
    protected Runnable onCountDownTrigger() {
        return this;
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        //过滤频繁移动
        if (System.currentTimeMillis() - lastMovementTime < 1000) {
            return;
        }
        long mayMovementTime = lastMovementTime;
        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
            float x = event.values[0];
            float y = event.values[1];
            float z = event.values[2];

            float acceleration = (float) Math.sqrt(x * x + y * y + z * z);

            if (Math.abs(acceleration - SensorManager.GRAVITY_EARTH) > THRESHOLD_ACCELEROMETER) {
                mayMovementTime = System.currentTimeMillis();
            }
        } else if (event.sensor.getType() == Sensor.TYPE_GYROSCOPE) {
            float x = event.values[0];
            float y = event.values[1];
            float z = event.values[2];

            float angularSpeed = (float) Math.sqrt(x * x + y * y + z * z);

            if (angularSpeed > THRESHOLD_GYROSCOPE) {
                mayMovementTime = System.currentTimeMillis();
            }
        }

        // 检查是否长时间未移动
        long intervalTime = mayMovementTime - lastMovementTime;
        if (intervalTime > 0 && intervalTime < TIME_THRESHOLD) {
            lastMovementTime = mayMovementTime;
            resetCountdown();
        }
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        //精度变化
    }

    @Override
    public void destroy() {
        super.destroy();
        sensorManager.unregisterListener(this);
        if (listener != null){
            resultWrapper = resultWrapper.newState(ProcessState.DESTROY);
            listener.onAsyncRiskStateChange(resultWrapper);
        }
    }

    @Override
    public void run() {
        if (listener != null){
            resultWrapper = resultWrapper.newResult(true);
            resultWrapper.inRisk(true);
            listener.onFindAsyncRisk(resultWrapper);
        }
    }
}
